package com.wh.db.jdbc.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.wh.lang.LogUtil;

/**
 * 封装了的SpringJDBC操作
 * 
 * @author washheart@163.com
 */
public class BaseJDBCOperations {
	private String name;
	private Connection cnn;

	public void initByConnection(Connection cnn) {
		this.cnn = cnn;
	}

	public boolean isClose() {
		if (cnn == null) return true;
		try {
			return cnn.isClosed();
		} catch (SQLException e) {
			if (LogUtil.rootLog.isErrorEnabled()) LogUtil.rootLog.error("检查数据库[" + name + "]是否关闭时出错", e);
			return false;
		}
	}

	public void saveOrUpdateAll() throws SQLException {
		// try {
		// cnn.commit();
		// } catch (SQLException ex) {
		// // String err = "同步数据库出错。DBURL=" + name;
		// try {
		// cnn.rollback();
		// } catch (Exception e) {}// end try
		// throw ex;
		// }
	}

	protected ResultSet query(String sql) throws SQLException {
		if (LogUtil.rootLog.isDebugEnabled()) LogUtil.rootLog.debug(sql);
		return cnn.createStatement().executeQuery(sql);
	}

	protected <T> List<T> resultSet2List(ResultSet rs, IJDBCRowMapper<T> mapper) throws SQLException {
		List<T> results = new ArrayList<T>();
		int rowNum = 0;
		while (rs.next()) {
			results.add(mapper.mapRow(rs, rowNum++));
		}
		return results;
	}

	public <T> List<T> query(String sql, IJDBCRowMapper<T> mapper) throws SQLException {
		return resultSet2List(query(sql), mapper);
	}

	public <T> T queryForObject(String sql, IJDBCRowMapper<T> mapper) throws SQLException {
		return resultSet2Object(query(sql), mapper);
	}

	protected <T> T resultSet2Object(ResultSet rs, IJDBCRowMapper<T> mapper) throws SQLException {
		return rs.next() ? mapper.mapRow(rs, 0) : null;
	}

	public <T> T queryForObject(String sql) throws SQLException {
		if (LogUtil.rootLog.isDebugEnabled()) LogUtil.rootLog.debug(sql);
		ResultSet rs = query(sql);
		if (rs.next()) return (T) rs.getObject(1);
		return null;
	}

	public boolean execute(String sql) throws SQLException {
		if (LogUtil.rootLog.isDebugEnabled()) LogUtil.rootLog.debug(sql);
		return cnn.createStatement().execute(sql);
	}

	public <T> void save(String sql, T t, IJDBCRowSetter<T> pss) throws SQLException {
		if (LogUtil.rootLog.isDebugEnabled()) LogUtil.rootLog.debug(sql);
		List<T> values = new ArrayList<T>(1);
		values.add(t);
		batchUpdate(sql, pss, values, 1);
	}

	/**
	 * 批量执行一些SQL
	 * 
	 * @param sql
	 * @param setter
	 *            数据转换工具，将对象设置到预计中
	 * @param objects
	 * @param batchSize
	 * @throws SQLException
	 */
	public <T> void batchUpdate(String sql, IJDBCRowSetter<T> setter, Collection<T> objects, int batchSize) throws SQLException {
		if (LogUtil.rootLog.isDebugEnabled()) LogUtil.rootLog.debug(sql);
		PreparedStatement ps = createPrepare(sql);
		batchUpdate(ps, setter, objects, batchSize);
	}

	protected <T> void batchUpdate(PreparedStatement ps, IJDBCRowSetter<T> setter, Collection<T> objects, int batchSize) throws SQLException {
		int n = 0, size = objects.size();
		for (T obj : objects) {
			setter.setValues(ps, obj);
			n++;
			ps.addBatch();
			if (n % batchSize == 0 || n == size) {
				ps.executeBatch();
			}
		}
	}

	protected PreparedStatement createPrepare(String sql) throws SQLException {
		if (LogUtil.rootLog.isDebugEnabled()) LogUtil.rootLog.debug(sql);
		return cnn.prepareStatement(sql);
	}
}